package yawning.mew.gui.tools;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import yawning.mew.character.ArmoryToonBuilder;
import yawning.mew.character.ArmoryToonBuilder.ArmoryToonBuildException;
import yawning.mew.character.Clazz;
import yawning.mew.character.Glyph;
import yawning.mew.character.Race;
import yawning.mew.character.Talent;
import yawning.mew.character.TalentTree;
import yawning.mew.character.Toon;
import yawning.mew.equipment.EquipSet;
import yawning.mew.equipment.EquipSet.Slot;
import yawning.mew.equipment.Item;

/**
 * Class that manages the character source for the gui to allow databinds with the UI interface.
 * @author Ceridan
 *
 */
public class CharacterDataSource {
	private ToonWrapper toon;
	private Map<String, TalentWrapper> talents;
	private Map<Integer,GlyphWrapper> glyphs;
	private EquipSet equipSet;
	
	private static Clazz[] BLOOD_ELF = {Clazz.DEATH_KNIGHT,Clazz.HUNTER,Clazz.MAGE,Clazz.PALADIN,Clazz.PRIEST,
	Clazz.ROGUE,Clazz.WARLOCK,Clazz.WARRIOR};
	private static Clazz[] DRAENEI = {Clazz.DEATH_KNIGHT,Clazz.HUNTER,Clazz.MAGE,Clazz.PALADIN,Clazz.PRIEST,
	Clazz.SHAMAN,Clazz.WARRIOR};
	private static Clazz[] DWARF= {Clazz.DEATH_KNIGHT,Clazz.HUNTER,Clazz.MAGE,Clazz.PALADIN,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.SHAMAN,Clazz.WARLOCK, Clazz.WARRIOR};
	private static Clazz[] GNOME= {Clazz.DEATH_KNIGHT,Clazz.MAGE,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.WARLOCK, Clazz.WARRIOR};
	private static Clazz[] GOBLIN= {Clazz.DEATH_KNIGHT,Clazz.HUNTER,Clazz.MAGE,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.SHAMAN,Clazz.WARLOCK, Clazz.WARRIOR};
	private static Clazz[] HUMAN= {Clazz.DEATH_KNIGHT,Clazz.HUNTER,Clazz.MAGE,Clazz.PALADIN,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.WARLOCK, Clazz.WARRIOR};
	private static Clazz[] NIGHT_ELF= {Clazz.DEATH_KNIGHT,Clazz.DRUID, Clazz.HUNTER,Clazz.MAGE,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.SHAMAN, Clazz.WARRIOR};
	private static Clazz[] ORC= {Clazz.DEATH_KNIGHT,Clazz.HUNTER,Clazz.MAGE,Clazz.ROGUE, Clazz.SHAMAN,
	Clazz.WARLOCK, Clazz.WARRIOR};
	private static Clazz[] TAUREN= {Clazz.DEATH_KNIGHT,Clazz.DRUID,Clazz.HUNTER,Clazz.PALADIN,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.SHAMAN, Clazz.WARRIOR};
	private static Clazz[] TROLL= {Clazz.DEATH_KNIGHT,Clazz.DRUID,Clazz.HUNTER,Clazz.MAGE,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.SHAMAN,Clazz.WARLOCK, Clazz.WARRIOR};
	private static Clazz[] UNDEAD= {Clazz.DEATH_KNIGHT,Clazz.HUNTER,Clazz.MAGE,Clazz.PRIEST,
	Clazz.ROGUE, Clazz.WARLOCK, Clazz.WARRIOR};
	private static Clazz[] WORGEN= {Clazz.DEATH_KNIGHT,Clazz.DRUID,Clazz.HUNTER,Clazz.MAGE,Clazz.PRIEST,
	Clazz.ROGUE,Clazz.WARLOCK, Clazz.WARRIOR};
	
	
	/**
	 * Constructor
	 * @param name
	 * 	The character's name
	 * @param server
	 * 	The character`s realm
	 * @throws BattleNetToonBuildException 
	 * 	Information about the exception.
	 */
	public CharacterDataSource(String name, String server, String region) throws ArmoryToonBuildException
	{
		ArmoryToonBuilder factory = new ArmoryToonBuilder();
		talents = new HashMap<String, TalentWrapper>();
		glyphs = new HashMap<Integer, GlyphWrapper>();
		factory.setName(name);
		factory.setRegion(region);
		factory.setServer(server);
		Toon rawToon;
		try {
			rawToon = factory.build();
			
			Talent[] classTalents = rawToon.mClass.getTalents();
			Glyph[] classGlyph = rawToon.mClass.getGlyphs();
			
			
			for (Talent talent : classTalents) {
				talents.put(talent.toString(), new TalentWrapper(talent, rawToon));
			}
			
			for (Glyph glyph : classGlyph) {
				glyphs.put(glyph.getGlyphId(), new GlyphWrapper(glyph, rawToon));
			}
			
			toon = new ToonWrapper(rawToon, name, region, server);
			equipSet = factory.getEquipSet();
		} catch (ArmoryToonBuildException e) {
			e.fillInStackTrace();
			toon = new ToonWrapper(name,region,server);
			e.printStackTrace();
		}
		
	}
	
	public CharacterDataSource()
	{
		toon = new ToonWrapper();
		
		talents = new HashMap<String, TalentWrapper>();
		glyphs = new HashMap<Integer, GlyphWrapper>();
	}
	
	public Item getItem(Slot slot)
	{
		return equipSet.mEquipmentMap.get(slot);
	}

	public Map<Integer,GlyphWrapper> getGlyphs(){return glyphs;}
	
	public GlyphWrapper[] getGlyphArray(){return glyphs.values().toArray(new GlyphWrapper[0]);}
	
	public ToonWrapper getToon(){return toon;}
	
	public Iterator<TalentWrapper> getTalentIterator()
	{
		return talents.values().iterator();
	}
	
	public TalentWrapper getTalentByName(String name)
	{
		return talents.get(name);
	}
	
	/**
	 * Gets the canonical name of the talent tree
	 * @param id
	 * 	Id of the talent tree.
	 * 	This parameter is a number between 0 and 2.
	 * @return
	 * 	The name of a talent tree
	 */
	public String getTalentTreeName(int id)
	{
		return toon.toon.mClass.getTalentTrees()[id].toString();
	}
	
	/**
	 * Get all the talents from specified tree
	 * @param id
	 * 	Id of the talent tree.
	 * 	This parameter is a number between 0 and 2.
	 * @return
	 * 	an iterator containing all the talents from a specific tree.
	 */
	public Iterator<Talent> getAllTalentsFromTree(int id)
	{
		if(id>2){return null;}
		TalentTree[] trees = toon.toon.mClass.getTalentTrees();
		
		ArrayList<Talent> talentList = new ArrayList<Talent>();
		
		Talent[] tals = toon.toon.mClass.getTalents();
		
		for (Talent talent : tals) {
			if(talent.getTree().equals(trees[id]))
			{
				talentList.add(talent);
			}
		}
		return talentList.iterator();
		
	}
	
	public Clazz[] getClassFromRace()
	{
		Race race = toon.getChar_Race();
		
		if(race == Race.BLOOD_ELF)
			return BLOOD_ELF;
		if(race == Race.DRAENEI)
			return DRAENEI;
		if(race == Race.DWARF)
			return DWARF;
		if(race == Race.GNOME)
			return GNOME;
		if(race == Race.GOBLIN)
			return GOBLIN;
		if(race == Race.HUMAN)
			return HUMAN;
		if(race == Race.NIGHT_ELF)
			return NIGHT_ELF;
		if(race == Race.ORC)
			return ORC;
		if(race == Race.TAUREN)
			return TAUREN;
		if(race == Race.TROLL)
			return TROLL;
		if(race == Race.UNDEAD)
			return UNDEAD;
		if(race == Race.WORGEN)
			return WORGEN;
			
		return null;
	}
}
